//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#ifndef __ELASTOS_EVENT_H__
#define __ELASTOS_EVENT_H__

class Thread;
class DzEventSet;
struct EventSetRefNode;

class DzEvent : public SyncObject
{
    friend class DzEventSet;

public:
    DzEvent(bool_t bManualReset = FALSE, EventState initialState = UNSIGNALED)
    {
        m_bManualReset  = bManualReset;
        m_uState        = initialState;
        m_eventSetRefList.Initialize();
    }

    void UninterruptibleWait(EventState *pState);
    void Wait(WaitResult *pResult, EventState *pState);

    void TryUninterruptibleWait(
        uint_t ticks, WaitResult *pResult, EventState *pState);

    void TryWait(uint_t ticks, WaitResult *pResult, EventState *pState);

    void Notify(EventState state = SIGNALED);
    void NotifyByIsr(EventState state = SIGNALED);

    void Clear()
    {
        m_uState = UNSIGNALED;
    }

private:
    void BindEventSet(EventSetRefNode *pEventSetRefNode);
    void UnbindEventSet(EventSetRefNode *pEventSetRefNode);

private:
    void WaiterReadyToUninterruptibleSleep();
    void WaiterReadyToUninterruptibleSleep(DzTimer *pBindingTimer);

    void WaiterReadyToSleep(WaitResult *pResult);
    void WaiterReadyToSleep(DzTimer *pBindingTimer, WaitResult *pResult);

    void WakeUpOneWaiter(uint_t uState);
    void WakeUpAllWaiters(uint_t uState);

    void WakeUpOneWaiterByIsr(uint_t uState);
    void WakeUpAllWaitersByIsr(uint_t uState);

public:
    bool_t      m_bManualReset;
    uint_t      m_uState;
    DLinkNode   m_eventSetRefList;
};

EXTERN ECode DzCreateEventObj(
                /* [in] */ Boolean manualReset,
                /* [in] */ EventState initialState,
                /* [out] */ IEvent **ppEvent);

EXTERN void DzNotifyEventObjByIsr(
                /* [in] */ IEvent *pEvent,
                /* [in] */ EventState state);

#endif //__ELASTOS_EVENT_H__
